package com.accesslimit.demo;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 漏桶算法
 *
 * @author sam
 */
public class LeakyBucket {

    // 桶容量
    int capacity = 10;

    // 当前水容量
    int water = 0;

    // 水流速度7/s
    int rate = 7;

    // 最后一次请求时间
    long lastTime = System.currentTimeMillis();

    // 创建一个线程池
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(5);

    public void aquire() {
        // 请求处理
        scheduledExecutorService.scheduleWithFixedDelay(() -> {
            // 当前时间
            long now = System.currentTimeMillis();

            // 计算当前水量（时间差水流量）
            water = (int) Math.max(0, (int) (water - (now - lastTime) / 1000 * rate));

            // 每次水滴量（请求数）
            int permits = (int) (Math.random() * 8 + 1);
//            System.out.println("请求数：" + permits + ", 当前桶余量：" + (capacity - water));

            lastTime = now;

            if ((capacity - water) < permits) {
                System.out.println("请求限流！");
                System.out.println("--桶剩余容量[限流] -> " + (capacity - water) + "；请求数 -> " + permits);
            } else {
                water += permits;
                System.out.println("请求放行！");
                System.out.println("--桶剩余容量[放行] -> " + (capacity - water) + "；请求数 -> " + permits);

            }
            System.err.println("桶信息：" + capacity);
        }, 0, 500, TimeUnit.MILLISECONDS);

    }

    public static void main(String[] args) {
        new LeakyBucket().aquire();
    }

}
